package controll

import (
	"fmt"
	"haodayizhi/global"
	"haodayizhi/model"
	mtype "haodayizhi/types"
	util "haodayizhi/utils"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

// 获取用户权限
func GetUserPermission(c *gin.Context) {
	idStr := c.Query("id")
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "Get user permission successfully",
	}
	userPermission := &mtype.UserPermission{}
	response.Result = userPermission
	id, err := strconv.Atoi(idStr)
	if err != nil || id <= 0 {
		util.CommonErrorHandler(c, "Invalid user ID", http.StatusBadRequest, nil, err)
		return
	}
	userRole := &model.UserRole{}
	usreRole, err := userRole.GetUserRoleByID(int64(id))
	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving user info:", http.StatusBadRequest, nil, err)
		return
	}
	// 利用角色id 查询用户的操作权限以及菜单权限
	roleRoute := &model.RoleRoute{}
	roleRoutes, err := roleRoute.GetRoutesByRoleID(usreRole.RoleID)
	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving user info:", http.StatusBadRequest, nil, err)
		return
	}
	// 只需要roleRoutes中的ID
	// 循环roleRoutes，查询route表，获取route的path和name
	for _, route := range roleRoutes {
		userPermission.Route = append(userPermission.Route, route.RoleID)
	}

	rolePerims, err := model.GetRolePermissionByRoleID(userRole.RoleID)

	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving user info:", http.StatusBadRequest, nil, err)
		return
	}
	for _, rolePerm := range rolePerims {
		userPermission.Opareate = append(userPermission.Opareate, rolePerm.PermissionID)
	}

	response.Result = userPermission
	c.JSON(http.StatusOK, response)
}

// 获取权限方法
func GetUserAuth(uid int64) (mtype.UserPermission, error) {
	userPermission := &mtype.UserPermission{}
	userRole := &model.UserRole{}
	usreRole, err := userRole.GetUserRoleByID(uid)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Error retrieving user info: %s", err))
		return *userPermission, nil
	}
	// 利用角色id 查询用户的操作权限以及菜单权限
	roleRoute := &model.RoleRoute{}
	roleRoutes, err := roleRoute.GetRoutesByRoleID(usreRole.RoleID)
	if err != nil {
		return *userPermission, err
	}
	// 循环roleRoutes，查询route表，获取route的path和name
	for _, route := range roleRoutes {
		userPermission.Route = append(userPermission.Route, route.RouteID)
	}

	rolePerims, err := model.GetRolePermissionByRoleID(userRole.RoleID)

	if err != nil {
		return *userPermission, err
	}
	for _, rolePerm := range rolePerims {
		userPermission.Opareate = append(userPermission.Opareate, rolePerm.PermissionID)
	}
	return *userPermission, nil
}

// 获取角色列表
func GetRoleList(c *gin.Context) {
	role := &model.Role{}
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "Get role list successfully",
	}

	RoleListParam := mtype.RoleListParam{}

	err := c.ShouldBindQuery(&RoleListParam)
	if err != nil {
		util.CommonErrorHandler(c, "Error parsing query parameters:", http.StatusBadRequest, nil, err)
		return
	}

	roles, err := role.GetRoleList(RoleListParam.Page, RoleListParam.Limit)
	if err != nil {
		util.CommonErrorHandler(c, "Error retrieving user info:", http.StatusBadRequest, nil, err)
		return
	}
	response.Result = roles
	c.JSON(http.StatusOK, response)
}

func LoginHandler(c *gin.Context) {
	var loginRequest struct {
		Email     string `json:"email"`
		Cellphone string `json:"cellphone"`
		Password  string `json:"password"`
		Mode      string `json:"mode"` // 登录模式，邮箱或手机号，默认是邮箱 emode phonemode emodecode phonemodecode
		Code      string `json:"code"` // 验证码
	}

	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "登录成功",
		Result: map[string]interface{}{
			"token": "",
		},
	}
	err := error(nil)
	uuidStr, _ := c.Cookie(global.UUID)
	cookiew, _ := c.Cookie(global.Cookie)
	redisToken, err := util.GetToken(loginRequest.Email)
	if uuidStr != "" && cookiew != "" {
		token, _ := util.GetUuidValue(uuidStr)
		if token == cookiew && redisToken != nil && redisToken == cookiew {
			response.Message = "用户已登录"
			response.Result = map[string]interface{}{
				"token": token,
			}
			c.JSON(http.StatusOK, response)
			return
		}
		// 清除redis中的uuidcookie
		util.RemoveUUIDFromSet(uuidStr)
		util.DelToken(loginRequest.Email)
		util.DelUserInfoByUuid(uuidStr)
	}

	if err := c.ShouldBindJSON(&loginRequest); err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Invalid input: %v", err))
		response.Code = http.StatusBadRequest
		response.Message = "Invalid input"
		response.Result = map[string]interface{}{
			"token": "",
		}
		c.JSON(http.StatusBadRequest, response)
		return
	}
	// 下面是邮箱密码，手机号密码模式
	mode := loginRequest.Mode
	if mode == "" {
		mode = "emode"
	}
	user := &model.User{}
	// 这是邮箱验证码模式，以及手机号验证码模式
	if mode == "emodecode" || mode == "phonemodecode" {
		// 验证验证码
		if yes, err := util.CheckCode(loginRequest.Code, loginRequest.Email, "login"); err != nil || !yes {
			util.CommonErrorHandler(c, "Error checking code:", http.StatusBadRequest, nil, err)
			return
		}

		if mode == "emodecode" {
			user, err = model.GetUserByEmail(loginRequest.Email)
		} else if mode == "phonemodecode" {
			user, err = model.GetUserByCellphone(loginRequest.Cellphone)
		}
		if err != nil {
			util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to get user: %v", err))
			util.CommonErrorHandler(c, "Error getting user:", http.StatusBadRequest, nil, err)
			return
		}

	}

	if mode == "emode" {
		user, err = model.GetUserByEmail(loginRequest.Email)
		if err != nil {
			response.Code = http.StatusBadRequest
			response.Message = "Invalid email"
			c.JSON(http.StatusBadRequest, response)
			return
		}
		fmt.Println(user)
		// 验证密码
		if !util.CheckPassword(user.Password, loginRequest.Password) {
			response.Code = http.StatusBadRequest
			response.Message = "Invalid password"
			c.JSON(http.StatusBadRequest, response)
			return
		}

	} else if mode == "phomode" {
		user, err = model.GetUserByCellphone(loginRequest.Cellphone)
		if err != nil {
			response.Code = http.StatusBadRequest
			response.Message = "Invalid cellphone"
			c.JSON(http.StatusBadRequest, response)
			return
		}
		// 验证密码
		if !util.CheckPassword(user.Password, loginRequest.Password) {
			response.Code = http.StatusBadRequest
			response.Message = "Invalid password"
			c.JSON(http.StatusBadRequest, response)
			return
		}

	}
	// 生成 JWT
	token, err := util.GenerateJWT(user.ID, user.Email)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to generate token: %v , who : %v", err, user))
		util.CommonErrorHandler(c, "Failed to generate token:", http.StatusBadRequest, nil, err)
		return
	}
	// 生成uuid
	uuid, err := util.GenerateUUID()
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to generate uuid: %v , who : %v", err, user))
		util.CommonErrorHandler(c, "Failed to generate uuid:", http.StatusBadRequest, nil, err)
		return
	}

	// 存放uuid 到redis中
	if err := util.AddUUIDToSet(uuid, token); err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to set uuid to redis: %v , who : %v", err, user))
		util.CommonErrorHandler(c, "Failed to set uuid to redis:", http.StatusBadRequest, nil, err)
		return
	}

	// 存入用户数据到 redis
	if err := util.SetUserInfoToRedis(user.Email+uuid, user); err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to set user to redis: %v, who : %v", err, user))
		util.CommonErrorHandler(c, "Failed to set user to redis:", http.StatusBadRequest, nil, err)
		return
	}

	// 存入token
	if err := util.SetTokenToRedis(user.Email, token); err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to set token to redis: %v, who : %v", err, user))
		util.CommonErrorHandler(c, "Failed to set token to redis:", http.StatusBadRequest, nil, err)
		return
	}

	response.Result = map[string]interface{}{
		"token": token,
	}

	c.SetCookie(global.UUID, uuid, 3600*24*7, "/", "", false, true)
	c.SetCookie(global.Cookie, token, 3600*24*7, "/", "", false, true)

	c.JSON(http.StatusOK, response)
}

func RegisterHandler(c *gin.Context) {

	var user model.User

	var registerParams struct {
		RePassword string
		model.User
	}
	response := mtype.ResponseType{
		Code:    http.StatusOK,
		Message: "注册成功",
		Result:  map[string]interface{}{"redirect": "/"},
	}
	if err := c.ShouldBindJSON(&registerParams); err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Invalid input: %v", err))
		response.Code = http.StatusBadRequest
		response.Message = "Invalid input"
		response.Result = map[string]interface{}{
			"redirect": "",
		}
		c.JSON(http.StatusBadRequest, response)
		return
	}
	fmt.Println(registerParams)
	// 如果两次密码不一致
	if registerParams.Password != registerParams.RePassword {
		response.Code = http.StatusBadRequest
		response.Message = "两次密码不一致"
		response.Result = map[string]interface{}{
			"redirect": "",
		}
		c.JSON(http.StatusBadRequest, response)
		return
	}

	// 哈希密码
	hash, err := util.EncryPassWord(registerParams.Password)
	if err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to hash password: %v", err))
		response.Code = http.StatusInternalServerError
		response.Message = "User registration failed"
		response.Result = map[string]interface{}{
			"redirect": "",
		}
		c.JSON(http.StatusInternalServerError, response)
		return
	}
	user.Username = registerParams.Username
	user.Password = hash
	user.Age = registerParams.Age
	user.Birth = registerParams.Birth
	user.Gender = registerParams.Gender
	user.Signature = registerParams.Signature
	user.Email = registerParams.Email
	user.Cellphone = registerParams.Cellphone
	user.AvatarURL = registerParams.AvatarURL

	// 保存用户到数据库
	if err := global.Db.Create(&user).Error; err != nil {
		util.LogMessage(util.LogTypeError, fmt.Sprintf("Failed to create user: %v", err))
		response.Code = http.StatusInternalServerError
		response.Message = "User registration failed"
		response.Result = map[string]interface{}{
			"redirect": "",
		}
		c.JSON(http.StatusInternalServerError, response)
		return
	}

	util.LogMessage(util.LogTypeInfo, fmt.Sprintf("User %s registered successfully", registerParams.Username))
	c.JSON(http.StatusOK, response)
}
